package edu.washington.cs.sounddetector.server.database;

import java.util.Collection;
import java.util.Date;
import java.util.List;

import javax.jdo.PersistenceManager;
import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.PrimaryKey;
import javax.jdo.annotations.Queries;
import javax.jdo.annotations.Query;
import javax.jdo.annotations.Serialized;

import edu.washington.cs.sounddetector.server.api.object.PeakEvent;

/**
 * Database table for saving notifications for user's phones.
 * 
 * @author the.dylan.price@gmail.com
 * 
 */
@PersistenceCapable
@Queries({
        @Query(
                name = "QUERY_BY_USER_RECEIVERPHONE",
                language = "JDOQL",
                value = "SELECT FROM edu.washington.cs.sounddetector.server.database.Notifications WHERE userId == :userId && receiverPhone == :receiverPhone"),
        @Query(
                name = "QUERY_BY_USER_RECEIVERPHONE_READ",
                language = "JDOQL",
                value = "SELECT FROM edu.washington.cs.sounddetector.server.database.Notifications WHERE userId == :userId && receiverPhone == :receiverPhone && read == :read"),
        @Query(
                name = "QUERY_BY_USER_RECEIVERPHONE_READ_GTDATE_LTDATE",
                language = "JDOQL",
                value = "SELECT FROM edu.washington.cs.sounddetector.server.database.Notifications WHERE userId == :userId && receiverPhone == :receiverPhone && read == :read && createdDate > :gtdate && createdDate < :ltdate") })
public class Notifications
{
    /**
     * Named query.
     * 
     * @param userId
     *            (String)
     * @param receiverPhone
     *            (ReceiverPhone)
     */
    public static final String QUERY_BY_USER_RECEIVERPHONE = "QUERY_BY_USER_RECEIVERPHONE";

    /**
     * Named query.
     * 
     * @param userId
     *            (String)
     * @param receiverPhone
     *            (ReceiverPhone)
     * @param read
     *            (boolean)
     */
    public static final String QUERY_BY_USER_RECEIVERPHONE_READ = "QUERY_BY_USER_RECEIVERPHONE_READ";

    /**
     * Named query.
     * 
     * @param userId
     *            (String)
     * @param receiverPhone
     *            (ReceiverPhone)
     * @param read
     *            (boolean)
     * @param greaterThanDate
     *            (Date)
     * @param lessThanDate
     *            (Date)
     */
    public static final String QUERY_BY_USER_RECEIVERPHONE_READ_GTDATE_LTDATE = "QUERY_BY_USER_RECEIVERPHONE_READ_GTDATE_LTDATE";

    @PrimaryKey
    @Persistent(valueStrategy = IdGeneratorStrategy.NATIVE)
    private long id;
    private Date createdDate;
    private boolean read;
    private String userId;
    private ReceiverPhone receiverPhone;
    private DbSoundClass soundClass;
    @Serialized
    private List<PeakEvent> peakEvents;

    public Notifications(DbSoundClass soundClass, ReceiverPhone receiverPhone,
            List<PeakEvent> peakEvents)
    {
        this.createdDate = new Date(System.currentTimeMillis());
        this.read = false;
        // TODO: change when we implement users
        this.userId = "1";
        this.soundClass = soundClass;
        this.receiverPhone = receiverPhone;
        this.peakEvents = peakEvents;
    }

    /**
     * @return the createdDate
     */
    public Date getCreatedDate()
    {
        return createdDate;
    }

    /**
     * @param createdDate
     *            the createdDate to set
     */
    public void setCreatedDate(Date createdDate)
    {
        this.createdDate = createdDate;
    }

    /**
     * @return the read
     */
    public boolean isRead()
    {
        return read;
    }

    /**
     * @param read
     *            the read to set
     */
    public void setRead(boolean read)
    {
        this.read = read;
    }

    /**
     * @param id
     *            the id to set
     */
    public void setId(long id)
    {
        this.id = id;
    }

    /**
     * @return the soundClass
     */
    public DbSoundClass getSoundClass()
    {
        return soundClass;
    }

    /**
     * @param soundClass
     *            the soundClass to set
     */
    public void setSoundClass(DbSoundClass soundClass)
    {
        this.soundClass = soundClass;
    }

    public String getUserId()
    {
        return userId;
    }

    public void setUserId(String userId)
    {
        this.userId = userId;
    }

    public ReceiverPhone getReceiverPhone()
    {
        return receiverPhone;
    }

    public void setReceiverPhone(ReceiverPhone receiverPhone)
    {
        this.receiverPhone = receiverPhone;
    }

    public List<PeakEvent> getPeakEvents()
    {
        return this.peakEvents;
    }

    public void setPeakEvents(List<PeakEvent> peakEvents)
    {
        this.peakEvents = peakEvents;
    }

    /**
     * @return the id
     */
    public long getId()
    {
        return id;
    }

    public static Collection<Notifications> query(PersistenceManager pm, String userId,
            ReceiverPhone receiverPhone)
    {
        javax.jdo.Query query = pm.newNamedQuery(Notifications.class,
                Notifications.QUERY_BY_USER_RECEIVERPHONE);
        @SuppressWarnings("unchecked")
        Collection<Notifications> result = (Collection<Notifications>) query.execute(userId,
                receiverPhone);
        return result;
    }

    public static Collection<Notifications> query(PersistenceManager pm, String userId,
            ReceiverPhone receiverPhone, boolean read)
    {
        javax.jdo.Query query = pm.newNamedQuery(Notifications.class,
                Notifications.QUERY_BY_USER_RECEIVERPHONE_READ);
        @SuppressWarnings("unchecked")
        Collection<Notifications> result = (Collection<Notifications>) query.execute(userId,
                receiverPhone, read);
        return result;
    }

    public static Collection<Notifications> query(PersistenceManager pm, String userId,
            ReceiverPhone receiverPhone, boolean read, Date greaterThanDate, Date lessThanDate)
    {
        javax.jdo.Query query = pm.newNamedQuery(Notifications.class,
                Notifications.QUERY_BY_USER_RECEIVERPHONE_READ_GTDATE_LTDATE);
        @SuppressWarnings("unchecked")
        Collection<Notifications> result = (Collection<Notifications>) query.executeWithArray(
                userId, receiverPhone, read, greaterThanDate, lessThanDate);
        return result;
    }
}
